home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / p_menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  5.4 KB  |  257 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "g_local.h"
  21.  
  22. // Note that the pmenu entries are duplicated
  23. // this is so that a static set of pmenu entries can be used
  24. // for multiple clients and changed without interference
  25. // note that arg will be freed when the menu is closed, it must be allocated memory
  26. pmenuhnd_t *PMenu_Open(edict_t *ent, pmenu_t *entries, int cur, int num, void *arg)
  27. {
  28.     pmenuhnd_t *hnd;
  29.     pmenu_t *p;
  30.     int i;
  31.  
  32.     if (!ent->client)
  33.         return NULL;
  34.  
  35.     if (ent->client->menu) {
  36.         gi.dprintf("warning, ent already has a menu\n");
  37.         PMenu_Close(ent);
  38.     }
  39.  
  40.     hnd = malloc(sizeof(*hnd));
  41.  
  42.     hnd->arg = arg;
  43.     hnd->entries = malloc(sizeof(pmenu_t) * num);
  44.     memcpy(hnd->entries, entries, sizeof(pmenu_t) * num);
  45.     // duplicate the strings since they may be from static memory
  46.     for (i = 0; i < num; i++)
  47.         if (entries[i].text)
  48.             hnd->entries[i].text = strdup(entries[i].text);
  49.  
  50.     hnd->num = num;
  51.  
  52.     if (cur < 0 || !entries[cur].SelectFunc) {
  53.         for (i = 0, p = entries; i < num; i++, p++)
  54.             if (p->SelectFunc)
  55.                 break;
  56.     } else
  57.         i = cur;
  58.  
  59.     if (i >= num)
  60.         hnd->cur = -1;
  61.     else
  62.         hnd->cur = i;
  63.  
  64.     ent->client->showscores = true;
  65.     ent->client->inmenu = true;
  66.     ent->client->menu = hnd;
  67.  
  68.     PMenu_Do_Update(ent);
  69.     gi.unicast (ent, true);
  70.  
  71.     return hnd;
  72. }
  73.  
  74. void PMenu_Close(edict_t *ent)
  75. {
  76.     int i;
  77.     pmenuhnd_t *hnd;
  78.  
  79.     if (!ent->client->menu)
  80.         return;
  81.  
  82.     hnd = ent->client->menu;
  83.     for (i = 0; i < hnd->num; i++)
  84.         if (hnd->entries[i].text)
  85.             free(hnd->entries[i].text);
  86.     free(hnd->entries);
  87.     if (hnd->arg)
  88.         free(hnd->arg);
  89.     free(hnd);
  90.     ent->client->menu = NULL;
  91.     ent->client->showscores = false;
  92. }
  93.  
  94. // only use on pmenu's that have been called with PMenu_Open
  95. void PMenu_UpdateEntry(pmenu_t *entry, const char *text, int align, SelectFunc_t SelectFunc)
  96. {
  97.     if (entry->text)
  98.         free(entry->text);
  99.     entry->text = strdup(text);
  100.     entry->align = align;
  101.     entry->SelectFunc = SelectFunc;
  102. }
  103.  
  104. void PMenu_Do_Update(edict_t *ent)
  105. {
  106.     char string[1400];
  107.     int i;
  108.     pmenu_t *p;
  109.     int x;
  110.     pmenuhnd_t *hnd;
  111.     char *t;
  112.     qboolean alt = false;
  113.  
  114.     if (!ent->client->menu) {
  115.         gi.dprintf("warning:  ent has no menu\n");
  116.         return;
  117.     }
  118.  
  119.     hnd = ent->client->menu;
  120.  
  121.     strcpy(string, "xv 32 yv 8 picn inventory ");
  122.  
  123.     for (i = 0, p = hnd->entries; i < hnd->num; i++, p++) {
  124.         if (!p->text || !*(p->text))
  125.             continue; // blank line
  126.         t = p->text;
  127.         if (*t == '*') {
  128.             alt = true;
  129.             t++;
  130.         }
  131.         sprintf(string + strlen(string), "yv %d ", 32 + i * 8);
  132.         if (p->align == PMENU_ALIGN_CENTER)
  133.             x = 196/2 - strlen(t)*4 + 64;
  134.         else if (p->align == PMENU_ALIGN_RIGHT)
  135.             x = 64 + (196 - strlen(t)*8);
  136.         else
  137.             x = 64;
  138.  
  139.         sprintf(string + strlen(string), "xv %d ",
  140.             x - ((hnd->cur == i) ? 8 : 0));
  141.  
  142.         if (hnd->cur == i)
  143.             sprintf(string + strlen(string), "string2 \"\x0d%s\" ", t);
  144.         else if (alt)
  145.             sprintf(string + strlen(string), "string2 \"%s\" ", t);
  146.         else
  147.             sprintf(string + strlen(string), "string \"%s\" ", t);
  148.         alt = false;
  149.     }
  150.  
  151.     gi.WriteByte (svc_layout);
  152.     gi.WriteString (string);
  153. }
  154.  
  155. void PMenu_Update(edict_t *ent)
  156. {
  157.     if (!ent->client->menu) {
  158.         gi.dprintf("warning:  ent has no menu\n");
  159.         return;
  160.     }
  161.  
  162.     if (level.time - ent->client->menutime >= 1.0) {
  163.         // been a second or more since last update, update now
  164.         PMenu_Do_Update(ent);
  165.         gi.unicast (ent, true);
  166.         ent->client->menutime = level.time;
  167.         ent->client->menudirty = false;
  168.     }
  169.     ent->client->menutime = level.time + 0.2;
  170.     ent->client->menudirty = true;
  171. }
  172.  
  173. void PMenu_Next(edict_t *ent)
  174. {
  175.     pmenuhnd_t *hnd;
  176.     int i;
  177.     pmenu_t *p;
  178.  
  179.     if (!ent->client->menu) {
  180.         gi.dprintf("warning:  ent has no menu\n");
  181.         return;
  182.     }
  183.  
  184.     hnd = ent->client->menu;
  185.  
  186.     if (hnd->cur < 0)
  187.         return; // no selectable entries
  188.  
  189.     i = hnd->cur;
  190.     p = hnd->entries + hnd->cur;
  191.     do {
  192.         i++, p++;
  193.         if (i == hnd->num)
  194.             i = 0, p = hnd->entries;
  195.         if (p->SelectFunc)
  196.             break;
  197.     } while (i != hnd->cur);
  198.  
  199.     hnd->cur = i;
  200.  
  201.     PMenu_Update(ent);
  202. }
  203.  
  204. void PMenu_Prev(edict_t *ent)
  205. {
  206.     pmenuhnd_t *hnd;
  207.     int i;
  208.     pmenu_t *p;
  209.  
  210.     if (!ent->client->menu) {
  211.         gi.dprintf("warning:  ent has no menu\n");
  212.         return;
  213.     }
  214.  
  215.     hnd = ent->client->menu;
  216.  
  217.     if (hnd->cur < 0)
  218.         return; // no selectable entries
  219.  
  220.     i = hnd->cur;
  221.     p = hnd->entries + hnd->cur;
  222.     do {
  223.         if (i == 0) {
  224.             i = hnd->num - 1;
  225.             p = hnd->entries + i;
  226.         } else
  227.             i--, p--;
  228.         if (p->SelectFunc)
  229.             break;
  230.     } while (i != hnd->cur);
  231.  
  232.     hnd->cur = i;
  233.  
  234.     PMenu_Update(ent);
  235. }
  236.  
  237. void PMenu_Select(edict_t *ent)
  238. {
  239.     pmenuhnd_t *hnd;
  240.     pmenu_t *p;
  241.  
  242.     if (!ent->client->menu) {
  243.         gi.dprintf("warning:  ent has no menu\n");
  244.         return;
  245.     }
  246.  
  247.     hnd = ent->client->menu;
  248.  
  249.     if (hnd->cur < 0)
  250.         return; // no selectable entries
  251.  
  252.     p = hnd->entries + hnd->cur;
  253.  
  254.     if (p->SelectFunc)
  255.         p->SelectFunc(ent, hnd);
  256. }
  257.